package com.ltedu.common.exception.handler;

import com.ltedu.common.enums.ErrorCodeEnum;
import com.ltedu.common.exception.BaseException;
import com.ltedu.common.vo.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * @ClassName: GlobalExceptionHandler
 * @Auther: Jerry
 * @Date: 2020/11/14 17:10
 * @Desctiption: 全局异常处理
 * @Version: 1.0
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 基础异常
     */
    @ResponseBody
    @ExceptionHandler(BaseException.class)
    public Result baseException(BaseException ex) {
        return Result.fail(ex.getDefaultMessage());
    }

    /**
     * 异常处理
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result<String> exceptionHanlder(Exception e) {
        logger.error("catch error {}", e);
        if (e instanceof BindException) {
            BindException be = (BindException) e;
            List<ObjectError> errors = be.getAllErrors();
            String[] args = new String[errors.size()];
            for (int i = 0; i < errors.size(); i++) {
                args[i] = errors.get(i).getDefaultMessage();
            }
            return Result.fail(ErrorCodeEnum.VALIDATE_ERROR.fillArgs(args.toString()));
        } else if(e instanceof MissingServletRequestParameterException){
            String parmaName = ((MissingServletRequestParameterException)e).getParameterName();
            return Result.fail(ErrorCodeEnum.PARAM_NAME_NOT_NULL.fillParam(parmaName, true));
        } else if(e instanceof ConstraintViolationException){
            Set<ConstraintViolation<?>> xErrors = ((ConstraintViolationException)e).getConstraintViolations();
            for (ConstraintViolation<?> violation : xErrors) {
                logger.warn("valid error: obj[{}], filed[{}], message[{}]", violation.getExecutableParameters(), violation.getInvalidValue(), violation.getMessage());
                String xError = violation.getMessage();
                return Result.fail(ErrorCodeEnum.VALID_PARAM_NAME_NOT_NULL.fillParam(xError, false));
            }
            return Result.fail(ErrorCodeEnum.SERVER_ERROR.getMessage());
        } else if(e instanceof MethodArgumentNotValidException){
            logger.error(e.getMessage(), e);
            BindingResult result = ((MethodArgumentNotValidException)e).getBindingResult();
            for (FieldError fieldError : result.getFieldErrors()) {
                logger.warn("valid error: obj[{}], filed[{}], message[{}]", fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage());
                String xError = fieldError.getDefaultMessage();
                return Result.fail(ErrorCodeEnum.VALID_PARAM_NAME_NOT_NULL.fillParam(xError,false));
            }
            return Result.fail(ErrorCodeEnum.SERVER_ERROR.getMessage());
        } else if(e instanceof BaseException){
            BaseException baseException = (BaseException) e;
            return Result.fail(baseException.getDefaultMessage());
        }else {
            return Result.fail(ErrorCodeEnum.SERVER_ERROR.getMessage());
        }

    }

}
